
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifi_hotspot.h"
#include "hi_wifi_api.h"
#include "lwip/ip_addr.h"
#include "lwip/netifapi.h"
#include "lwip/sockets.h"
#include "hi_time.h"


#include "kv_store.h"

#include "cJSON.h"

static volatile int g_hotspotStarted = 0;

static void OnHotspotStateChanged(int state)
{
    printf("OnHotspotStateChanged: %d.\r\n", state);
    if (state == WIFI_HOTSPOT_ACTIVE) {
        g_hotspotStarted = 1;
    } else {
        g_hotspotStarted = 0;
    }
}

static volatile int g_joinedStations = 0;

static void PrintStationInfo(StationInfo* info)
{
    if (!info) return;
    static char macAddress[32] = {0};
    unsigned char* mac = info->macAddress;
    snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X",
        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    printf(" PrintStationInfo: mac=%s, reason=%d.\r\n", macAddress, info->disconnectedReason);
}

static void OnHotspotStaJoin(StationInfo* info)
{
    g_joinedStations++;
    PrintStationInfo(info);
    printf("+OnHotspotStaJoin: active stations = %d.\r\n", g_joinedStations);
}

static void OnHotspotStaLeave(StationInfo* info)
{
    g_joinedStations--;
    PrintStationInfo(info);
    printf("-OnHotspotStaLeave: active stations = %d.\r\n", g_joinedStations);
}

WifiEvent g_defaultWifiEventListener = {
    .OnHotspotStaJoin = OnHotspotStaJoin,
    .OnHotspotStaLeave = OnHotspotStaLeave,
    .OnHotspotStateChanged = OnHotspotStateChanged,
};

static struct netif* g_iface = NULL;

int StartHotspot(const HotspotConfig* config)
{
    WifiErrorCode errCode = WIFI_SUCCESS;

    errCode = RegisterWifiEvent(&g_defaultWifiEventListener);
    printf("RegisterWifiEvent: %d\r\n", errCode);

    errCode = SetHotspotConfig(config);
    printf("SetHotspotConfig: %d\r\n", errCode);

    g_hotspotStarted = 0;
    errCode = EnableHotspot();
    printf("EnableHotspot: %d\r\n", errCode);

    while (!g_hotspotStarted) {
        osDelay(10);
    }
    printf("g_hotspotStarted = %d.\r\n", g_hotspotStarted);

    g_iface = netifapi_netif_find("ap0");
    if (g_iface) {
        ip4_addr_t ipaddr;
        ip4_addr_t gateway;
        ip4_addr_t netmask;

        IP4_ADDR(&ipaddr,  192, 168, 1, 1);     
        IP4_ADDR(&gateway, 192, 168, 1, 1);     
        IP4_ADDR(&netmask, 255, 255, 255, 0);   
        err_t ret = netifapi_netif_set_addr(g_iface, &ipaddr, &netmask, &gateway);
        printf("netifapi_netif_set_addr: %d\r\n", ret);

        ret = netifapi_dhcps_start(g_iface, 0, 0); 
        printf("netifapi_dhcp_start: %d\r\n", ret);
    }
    return errCode;
}

void StopHotspot(void)
{
    if (g_iface) {
        err_t ret = netifapi_dhcps_stop(g_iface);  
        printf("netifapi_dhcps_stop: %d\r\n", ret);
    }

    WifiErrorCode errCode = UnRegisterWifiEvent(&g_defaultWifiEventListener);
    printf("UnRegisterWifiEvent: %d\r\n", errCode);

    errCode = DisableHotspot();
    printf("EnableHotspot: %d\r\n", errCode);
}


int WifiHotspot(void)
{
    
    WifiErrorCode errCode;
    HotspotConfig config = {0};

    strcpy(config.ssid, "Car-AP");
    config.securityType = WIFI_SEC_TYPE_OPEN; // WIFI_SEC_TYPE_PSK;
    config.band = HOTSPOT_BAND_TYPE_5G; // HOTSPOT_BAND_TYPE_2G;
    config.channelNum = 7;

    osDelay(10);

    printf("starting AP ...\r\n");
    errCode = StartHotspot(&config);
    printf("StartHotspot: %d\r\n", errCode);
    return errCode;
}


void start_dmssocket(void)
{
    int ret;
    struct sockaddr_in servaddr;    
    char recvline[1024];
    cJSON *recvjson;    

    int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
 
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(30001);

    bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    while(1)
    {
        struct sockaddr_in addrClient;
        int sizeClientAddr = sizeof(struct sockaddr_in);

        memset(recvline, sizeof(recvline), 0);
        ret = recvfrom(sockfd, recvline, 1024, 0, (struct sockaddr*)&addrClient,(socklen_t*)&sizeClientAddr);
        
        if(ret>0)
        {
            char *pClientIP =inet_ntoa(addrClient.sin_addr);
 
            printf("udp %s-%d(%d) says:%s\n",pClientIP,ntohs(addrClient.sin_port),addrClient.sin_port, recvline);
                                
            recvjson = cJSON_Parse(recvline);
            
            if(recvjson != NULL){
                char *ssid= cJSON_GetObjectItem(recvjson, "ssid")->valuestring;
                char *key= cJSON_GetObjectItem(recvjson, "key")->valuestring;
                char *carmqip= cJSON_GetObjectItem(recvjson, "carmqip")->valuestring;
                char *carmqport= cJSON_GetObjectItem(recvjson, "carmqport")->valuestring;
                char *carmquser= cJSON_GetObjectItem(recvjson, "carmquser")->valuestring;
                char *carmqpassword= cJSON_GetObjectItem(recvjson, "carmqpassword")->valuestring;
                char *carmqpush= cJSON_GetObjectItem(recvjson, "carmqpush")->valuestring;
                char *carmqsub= cJSON_GetObjectItem(recvjson, "carmqsub")->valuestring;
                
                UtilsSetValue("ssid",ssid);
                UtilsSetValue("key",key);
                UtilsSetValue("carmqip",carmqip);
                UtilsSetValue("carmqport",carmqport);
                UtilsSetValue("carmquser",carmquser);
                UtilsSetValue("carmqpassword",carmqpassword);
                UtilsSetValue("carmqpush",carmqpush);
                UtilsSetValue("carmqsub",carmqsub);
                strcpy(recvline,"配网成功！");
                ret = sendto(sockfd, recvline, strlen(recvline), 0, (struct sockaddr *)&addrClient, sizeof(addrClient));
                if (ret <= 0) {
                    printf("send failed, %ld!\r\n", ret);
                }
                printf("send message {%s} %ld done!\r\n", recvline, ret);
                cJSON_Delete(recvjson);
                break;
            }

        }
    }
}
